import http from "http";
import mgrRecord from "./mgrRecord";


//--------------- 存储数据结构 ------------------
type UserInfo = {
    password: string;
    name: string;
    birthday?: number[];
    gift?: number;
    data: string;
}


type FrdInfo = {
    friends: { username: string, recentMessageDateTime: number }[],
    waitings: string[],
}





//--------------- 协议数据结构 ------------------


type FRIENDLIST = {
    friends: FriendInfo[];
    waitings: FriendInfo[];
}


type FRIENDFINDLIST = {
    users: FriendInfo[];
}


type FriendInfo = {
    username: string;
    userID: number;
    nickname: string;
    score: number;
    level: number;
    // agreeMessage: number;
    loginDateTime: number;
    recentMessageDateTime: number;
    playDateTime: number;
    character?: ServerItemInfo;
    skills?: ServerItemInfo[];
    treasures?: ServerItemInfo[];
}


type ServerItemInfo = {
    i: number;//itemID
    o: string;//itemOriginalID itemIndex
    l: number;//level
    s: number;//slot
}


type USERDETAIL = {
    nickname: string;
    level: number;
    score: number;
    bestCcore: number;
    leagueGrade: number;
    character: string;
    skills: string;
    treasures: string;

    equipedChar: string,
    equipedSkills: string,
    equipedTreasures: string,
}


type UserDetailInfo = {
    nickname: string;
    level: number;
    score: number;
    bestCcore: number;
    leagueGrade: number;
    character?: ServerItemInfo;
    skills?: ServerItemInfo[];
    treasures?: ServerItemInfo[];
}


export function OnRecieve(reqObj: any, rsp: http.ServerResponse) {
    if (typeof reqObj == "object") {
        for (const cmd in reqObj) {
            try {
                let jsonObj = JSON.parse(reqObj[cmd]);

                switch (cmd) {
                    case "login":
                        login(jsonObj, rsp);
                        break;
                    case "register":
                        register(jsonObj, rsp);
                        break;
                    case "setname":
                        setname(jsonObj, rsp);
                        break;
                    case "setlevel":
                        setlevel(jsonObj, rsp);
                        break;
                    case "friendlist":
                        friendlist(jsonObj, rsp);
                        break;
                    case "friendrequest":
                        friendrequest(jsonObj, rsp);
                        break;
                    case "friendaccept":
                        friendaccept(jsonObj, rsp);
                        break;
                    case "friendrefuse":
                        friendrefuse(jsonObj, rsp);
                        break;
                    case "frienddelete":
                        frienddelete(jsonObj, rsp);
                        break;
                    case "friendsuggest":
                        friendsuggest(jsonObj, rsp);
                        break;
                    case "friendgift":
                        friendgift(jsonObj, rsp);
                        break;
                    case "friendinfo":
                        friendinfo(jsonObj, rsp);
                        break;



                    case "saverecord":
                        saverecord(jsonObj, rsp);
                        break;


                    case "gm_save":
                        gm_savedata(jsonObj, rsp);
                        break;
                    case "gm_getgdata":
                        gm_getgdata(jsonObj, rsp);
                        break;
                    case "gm_changeuser":
                        gm_change_use(jsonObj, rsp);
                        break;
                    case "gm_getjsondata":
                        gm_get_json_data(jsonObj, rsp);
                        break;
                    case "gm_setjsondata":
                        gm_set_json_data(jsonObj, rsp);
                        break;
                }
            } catch (error) {
                console.error("OnRecieve err:", error);
            }
        }
    }
}










// ------------------ 请求部分 ------------------
function login(data: { username: string, password: string }, rsp: http.ServerResponse) {
    if (data.username && data.password) {
        let user = getUserInfo(data.username);
        if (user && user.name != "") {
            if (user.password == data.password) {
                let gift = user.gift || 0;
                user.gift = 0;
                let result = { code: 1, data: user.data, gift: gift, bir: user.birthday, childLevel: getChildLevel(user.birthday) };
                if (gift > 0)
                    mgrRecord.forceWrite();

                rsp.write(JSON.stringify(result));
                return;
            }
        }
    }

    rsp.write(JSON.stringify({ code: 0 }));
}


function register(data: { username: string, password: string, birthday: number[] }, rsp: http.ServerResponse) {
    if (data.username && data.password) {
        let user = getUserInfo(data.username);
        if (!user || user.name == "") {
            setUserInfo(data.username, data.password, "");
            user = getUserInfo(data.username);
            user.birthday = data.birthday;
            user.birthday[1]--;
            rsp.write("ok");
        } else {
            console.log("register fail:", data.username);
            rsp.write("fail");
        }
    }
}


function setname(data: { username: string, password: string, name: string }, rsp: http.ServerResponse) {
    if (data.username && data.password && data.name) {
        let user = getUserInfo(data.username);
        if (user && user.password == data.password && user.name == "") {
            setUserInfo(data.username, data.password, data.name);
            let newUser = getUserInfo(data.username);
            newUser.birthday = user.birthday;
            rsp.write(JSON.stringify({ code: 1, bir: user.birthday, childLevel: getChildLevel(user.birthday) }));
            mgrRecord.forceWrite();
        } else {
            rsp.write(JSON.stringify({ code: 0 }));
        }
    }
}


function setlevel(data: { username: string, level: number }, rsp: http.ServerResponse) {
    if (!data.username) return;
    rsp.write("fail");
}


function friendlist(data: { username: string }, rsp: http.ServerResponse) {
    if (!data.username) return;

    let all = getFriends(data.username);

    let frds: FriendInfo[] = [];
    let waits: FriendInfo[] = [];

    let curTime = Math.floor(Date.now() / 1000);
    for (let i = 0; i < all.friends.length; i++) {
        let user = getUserInfo(all.friends[i].username);
        if (user) {
            let user_data = safeParseUerData(user.data, all.friends[i].username);
            if (user_data) {
                frds.push({
                    username: all.friends[i].username,
                    userID: 0,
                    nickname: user.name,
                    score: 0,
                    level: user_data.op_name,
                    loginDateTime: 0,
                    recentMessageDateTime: curTime - all.friends[i].recentMessageDateTime,
                    playDateTime: 0,
                })
            }
        }
    }

    for (let i = 0; i < all.waitings.length; i++) {
        let user = getUserInfo(all.waitings[i]);
        if (user) {
            let user_data = safeParseUerData(user.data, all.waitings[i]);
            if (user_data) {
                waits.push({
                    username: all.waitings[i],
                    userID: 0,
                    nickname: user.name,
                    score: 0,
                    level: user_data.op_name,
                    loginDateTime: 0,
                    recentMessageDateTime: 0,
                    playDateTime: 0,
                })
            }
        }
    }

    let friends: FRIENDLIST = {
        friends: frds,
        waitings: waits,
    };

    rsp.write(JSON.stringify(friends));
}


function friendrequest(data: { username: string, fusername: string }, rsp: http.ServerResponse) {
    let fInfo = getFriends(data.fusername);
    let bWaiting = false;
    for (let i = 0; i < fInfo.waitings.length; i++) {
        if (fInfo.waitings[i] == data.username) {
            // 也算邀请成功
            bWaiting = true;
            break;
        }
    }

    if (!bWaiting)
        fInfo.waitings.push(data.username);

    rsp.write("ok");
}


function friendaccept(data: { username: string, fusername: string }, rsp: http.ServerResponse) {
    let fInfo = getFriends(data.username);
    for (let i = 0; i < fInfo.waitings.length; i++) {
        if (fInfo.waitings[i] == data.fusername) {
            fInfo.waitings.splice(i, 1);

            // 互加好友
            addFriend(data.username, data.fusername);
            addFriend(data.fusername, data.username);

            rsp.write("ok");
            return;
        }
    }

    rsp.write("fail");
}


function friendrefuse(data: { username: string, fusername: string }, rsp: http.ServerResponse) {
    let all = getFriends(data.username);
    for (let i = 0; i < all.waitings.length; i++) {
        if (all.waitings[i] == data.fusername) {
            all.waitings.splice(i, 1);
            rsp.write("ok");
            return;
        }
    }
    rsp.write("fail");
}


function frienddelete(data: { username: string, fusername: string }, rsp: http.ServerResponse) {
    let all = getFriends(data.username);
    for (let i = 0; i < all.friends.length; i++) {
        if (all.friends[i].username == data.fusername) {
            all.friends.splice(i, 1);
            rsp.write("ok");
            return;
        }
    }

    rsp.write("fail");
}


function friendsuggest(data: { username: string }, rsp: http.ServerResponse) {
    if (!data.username) return;

    let allfriend = getFriends(data.username);

    let usermap = {};
    usermap[data.username] = true;
    for (let i = 0; i < allfriend.friends.length; i++) {
        usermap[allfriend.friends[i].username] = true;
    }

    for (let i = 0; i < allfriend.waitings.length; i++) {
        usermap[allfriend.waitings[i]] = true;
    }

    let alluser = getAllUser();
    // 最多推荐5个
    let count = 5;
    let users: FriendInfo[] = [];
    for (const username in alluser) {
        const user = alluser[username];
        if (!usermap[username]) {
            let user_data = safeParseUerData(user.data, username);
            if (user_data) {
                let frd: FriendInfo = {
                    username: username,
                    userID: 0,
                    nickname: user.name,
                    score: 0,
                    level: user_data.op_name,
                    loginDateTime: 0,
                    recentMessageDateTime: 0,
                    playDateTime: 0,
                }
                users.push(frd);
                count--;
                if (count <= 0) {
                    break;
                }
            }
        }
    }

    let friends: FRIENDFINDLIST = {
        users: users,
    };

    rsp.write(JSON.stringify(friends));
}


function friendgift(data: { username: string, fusername: string }, rsp: http.ServerResponse) {
    let user = getUserInfo(data.fusername);
    if (user) {
        let curGift = user.gift || 0;
        user.gift = curGift + 10;

        let friend = getFriend(data.username, data.fusername);
        if (friend) {
            let curTime = Math.floor(Date.now() / 1000);
            friend.recentMessageDateTime = curTime;
        }

        rsp.write("ok");
    } else {
        rsp.write("fail");
    }
}


function friendinfo(data: { username: string, fusername: string }, rsp: http.ServerResponse) {
    let user = getUserInfo(data.fusername);
    if (user) {
        let user_data = safeParseUerData(user.data, data.fusername);

        if (user_data) {
            let userDetail: USERDETAIL = {
                nickname: user.name,
                level: user_data.op_name,
                score: 0,
                bestCcore: 0,
                leagueGrade: 0,
                character: user_data.op_m_StanceInfos,
                skills: user_data.op_m_MystiqueInfos,
                treasures: user_data.op_ArtifactInfos,

                equipedChar: user_data.op_EquipedStance,
                equipedSkills: user_data.op_EquipedMystiques,
                equipedTreasures: user_data.op_EquipedArtifacts,
            }

            rsp.write(JSON.stringify(userDetail));
        }
    } else {
        rsp.write("fail");
    }
}


function saverecord(data: { username: string, data: string }, rsp: http.ServerResponse) {
    let user = getUserInfo(data.username);
    if (user && data.data) {
        user.data = data.data;
        mgrRecord.forceWrite();
        // let dataobj = JSON.parse(data.data);
        // console.log(dataobj);
        rsp.write("ok");
    } else {
        rsp.write("fail");
    }
}



function gm_savedata(data: { deviceName: string }, rsp: http.ServerResponse) {
    console.log(`[${data.deviceName}] save data.`);
    mgrRecord.forceWrite();
    rsp.write("ok");
}


function gm_getgdata(data: { deviceName: string }, rsp: http.ServerResponse) {
    console.log(`[${data.deviceName}] get gdata.`);
    rsp.write(mgrRecord.getAllDataStr());
}


function gm_change_use(data: { deviceName: string, username: string, password: string, name: string, birthday?: number[] }, rsp: http.ServerResponse) {
    let user = getUserInfo(data.username);
    if (user) {
        user.password = data.password;
        user.name = data.name;
        if (data.birthday) {
            user.birthday = data.birthday;
        }
    }
}


function gm_get_json_data(data: { deviceName: string }, rsp: http.ServerResponse) {
    console.log(`[${data.deviceName}] get gdata.`);
    rsp.write(mgrRecord.getAllJsonStr());
}


function gm_set_json_data(data: { deviceName: string, data: string }, rsp: http.ServerResponse) {
    console.log(`[${data.deviceName}] get gdata.`);
    mgrRecord.readFromJsonStr(data.data);
}













// ------------------ 逻辑部分 ------------------
function _checkMonth(deltaM: number, deltaD: number): boolean {
    if (deltaM > 0) {
        return false;
    } else if (deltaM < 0) {
        return true;
    }

    if (deltaD > 0) {
        return false;
    }

    return true;
}


/** 18岁以上0，16岁1，8岁2，8岁以下3 */
function getChildLevel(birthday?: number[]): number {
    if (!birthday) return 0;

    // 看是否满18岁
    let dateBirthday = new Date(birthday[0], birthday[1], birthday[2], 0, 0, 0, 0);
    let dateNow = new Date(Date.now());
    dateNow.setHours(0, 0, 0, 0);

    let deltaY = dateNow.getFullYear() - dateBirthday.getFullYear();
    let deltaM = dateNow.getMonth() - dateBirthday.getMonth();
    let deltaD = dateNow.getDay() - dateBirthday.getDay();

    let bFull = _checkMonth(deltaM, deltaD);

    if (deltaY > 18) return 0;
    if (deltaY == 18) return bFull ? 0 : 1;

    if (deltaY > 16) return 1;
    if (deltaY == 16) return bFull ? 1 : 2;

    if (deltaY > 8) return 2;
    if (deltaY == 8) return bFull ? 2 : 3;

    return 3;
}


function safeParseUerData(jsonStr: string, username: string) {
    try {
        return JSON.parse(jsonStr);
    } catch (error) {
        console.error(error);
        console.error(`can't parse user data:[${username}]`);
    }
    return null;
}





function getAllUser(): { [user: string]: UserInfo } {
    let all = mgrRecord.getData("users");
    if (!all) {
        all = {};
        mgrRecord.setData("users", all);
    }
    return all;
}


function getUserInfo(username: string): UserInfo {
    let all = getAllUser();
    return all[username];
}


/** 这个方法会重置存档 */
function setUserInfo(username: string, password: string, name: string) {
    let all = getAllUser();
    all[username] = { password: password, name: name, data: "empty" };
    mgrRecord.setData("users", all);
}


function getFriends(username: string): FrdInfo {
    let all: { [username: string]: FrdInfo } = mgrRecord.getData("friends");
    if (!all) {
        all = {};
        mgrRecord.setData("friends", all);
    }

    let frd = all[username];
    if (!frd) {
        frd = { friends: [], waitings: [] };
        all[username] = frd;
    } else {
        if (frd.friends.length > 0) {
            // 兼容老存档
            if (typeof frd.friends[0] === "string") {
                let curTime = Math.floor(Date.now() / 1000);
                for (let i = 0; i < frd.friends.length; i++) {
                    let fuername: any = frd.friends[i];
                    frd.friends[i] = { username: fuername, recentMessageDateTime: curTime };
                }

                mgrRecord.setData("friends", all);
            }
        }
    }
    return frd;
}


function getFriend(username: string, user2: string) {
    let all = getFriends(username).friends;
    for (let i = 0; i < all.length; i++) {
        if (all[i].username == user2) {
            return all[i];
        }
    }
    return null;
}


function addFriend(user1: string, user2: string): void {
    let fInfo = getFriends(user1);
    let bFriend = false;
    for (let i = 0; i < fInfo.friends.length; i++) {
        if (fInfo.friends[i].username == user2) {
            bFriend = true;
            break;
        }
    }

    if (!bFriend) {
        fInfo.friends.push({ username: user2, recentMessageDateTime: 0 });
    }
}



